package pri.zxx.excelgenerate.dataentity.tabledata;

import com.alibaba.fastjson.JSON;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import pri.zxx.excelgenerate.dataentity.entity.*;
import pri.zxx.excelgenerate.dataentity.module.ModuleCreator;
import pri.zxx.excelgenerate.excelhanler.ExcelUtil;
import pri.zxx.excelgenerate.excelhanler.RowHeightConstant;
import pri.zxx.excelgenerate.excelhanler.excelentity.CustomCell;
import pri.zxx.excelgenerate.excelhanler.excelentity.CustomRow;

import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 模块创建模板
 */
@Data
@Accessors(chain = true)
@Component
@Slf4j
public abstract class MultiTitleModuleCreatorTemplate implements ModuleCreator {


    protected static final String JOIN_DECILITER = "__";


    @Override
    public abstract List<ModuleMetaInfo> creator(CreatRequest creatRequest);

    @Override
    public abstract ModuleInfoEnum moduleInfo();

    @Override
    public TableDefinition moduleMetaInfoHandle(TableDefinition tableDefinition, CreatRequest creatRequest) {
        CreatRequest.TableCreateReq tcr = creatRequest.getTableCreateReq();
        //创建Range表格
        /* ***************************   处理范围标题       **************************/
        Boolean weight = ExcelUtil.isWeight(creatRequest);
        String suffix = "";
        if (weight != null) {
            suffix = weight ? " kg" : " day";
        }
        List<CreatRequest.Range> ranges = creatRequest.getRanges();
        int rangesLen;

        if (ranges != null && !ranges.isEmpty() && creatRequest.getPredictionTypeEnum() != PredictionTypeEnum.STARTING_PIGS) {
            rangesLen = ranges.size();
            if (tcr.getLoadRanges()) {
                List<CustomCell> rangeCells = ExcelUtil.genarateCellsByRange(4, true, rangesLen);
                for (int i = 1; i < rangeCells.size(); ) {
                    for (CreatRequest.Range r : ranges) {
                        rangeCells.get(i).setValue(r.getStart() + " - " + r.getEnd() + suffix);
                        i++;
                    }
                }
                tableDefinition.setRanges(rangeCells);
            }
        } else {
            //仔猪没有范围选项
            rangesLen = 1;
        }

        /* ***************************   处理标题      **************************/
        List<String> tl = tcr.getTitleList();
        if (tl != null && !tl.isEmpty()) {
            List<CustomCell> titleCells = ExcelUtil.genarateCellsByRange(4, true, rangesLen * tcr.getMULT());
            for (int i = 1; i < titleCells.size(); ) {
                for (String string : tl) {
                    titleCells.get(i).setValue(string);
                    i++;
                }
            }
            tableDefinition.setTitles(titleCells);
        }
        return tableDefinition;
    }


    @Override
    public TableDefinition dataHandle(TableDefinition tableDefinition, CreatRequest creatRequest) {
        CreatRequest.TableCreateReq tcr = creatRequest.getTableCreateReq();
        Object unLoadData = tableDefinition.getUnLoadData();
        if (Objects.nonNull(unLoadData)) {
            int rangesLen;
            if (creatRequest.getRanges() == null || creatRequest.getRanges().isEmpty() || creatRequest.getPredictionTypeEnum() == PredictionTypeEnum.STARTING_PIGS) {
                rangesLen = 1;
            } else {
                rangesLen = creatRequest.getRanges().size();
            }

            /* ***************************    数据行定义      **************************/
            List<CustomCell> dataCells = ExcelUtil.genarateCellsByRange(4, true, rangesLen * tcr.getMULT());

            Map<String, List<CellData>> filedMap = ExcelUtil.getTableDefinition(tableDefinition.getDataClass());

            //存放所有的数据行信息
            List<CustomRow> rows = new ArrayList<>();

            //存放每行的单元格数据
            Map<String, List<CustomCell>> rowMap = new LinkedHashMap<>();

            /* ***************************    处理数据      **************************/

            List<Object> opVitamins = (List<Object>) unLoadData;

            int outStart = 0;
            for (Object obj : opVitamins) {

                for (Map.Entry<String, List<CellData>> entry : filedMap.entrySet()) {
                    String s = entry.getKey();
                    List<CellData> infos = entry.getValue();

                    AtomicInteger innerStart = new AtomicInteger(1);
                    int finalOutStart = outStart;
                    infos.stream().sorted(Comparator.comparingInt(CellData::getOrder)).forEach(m1 -> {
                        CustomCell nowC = dataCells.get(innerStart.get() + finalOutStart);
                        Field field = m1.getField();
                        field.setAccessible(true);
                        try {
                            List<CustomCell> nowS = rowMap.get(s);
                            if (nowS == null || nowS.isEmpty()) {
                                nowS = new ArrayList<>();
                            }
                            Object o = field.get(obj);
                            if (Objects.isNull(o)) {
                                o = "";
                            }
                            nowS.add(new CustomCell(o.toString(), nowC.getStart(), nowC.getEnd()));
                            rowMap.put(s, nowS);
                            innerStart.getAndIncrement();
                        } catch (IllegalAccessException e) {
                            log.error("加载表格数据异常：request:{},module:{},field:{}", JSON.toJSONString(creatRequest), moduleInfo().getName(), field.getName(), e);
                        }
                    });
                    innerStart.set(0);
                }
                Optional<Integer> max = filedMap.values().stream().map(List::size).max(Integer::compareTo);
                if (max.isPresent()) {
                    outStart = outStart + max.get();
                }
            }

            rowMap.forEach((s, customCells) -> {
                customCells.add(0, new CustomCell(s, dataCells.get(0).getStart(), dataCells.get(0).getEnd()));
                rows.add(CustomRow.createRow(customCells, RowHeightConstant.ROW_HEIGHT_18));
            });
            tableDefinition.setRowsData(rows);
        } else {
            log.info("模块：【{} 】待装载的数据为空", moduleInfo().getName());
        }
        return tableDefinition;
    }


    /**
     * 默认通过反射获取单个对象中字段value
     */
    public TableDefinition loadObjectData(TableDefinition tableDefinition, CreatRequest creatRequest, ExcelData comInfo, boolean tw) {
        Class<? extends ExcelData> byType = getByType(creatRequest.getPredictionTypeEnum());
        int max = 6;
        int cellCount;
        if (tw) {//属性占用2格 处理多行数据
            Map<String, List<CellData>> tableDefinition1 = ExcelUtil.getTableDefinition(byType);
            if (tableDefinition1 != null && !tableDefinition1.isEmpty()) {
                cellCount = 4;
                //占用多少行
                Collection<List<CellData>> values = tableDefinition1.values();
                int size = values.size();
                int rowsCount = (int) Math.ceil(size / 2.0); //占用多少行
                List<CustomRow> rows = new ArrayList<>(rowsCount);

                List<CustomCell> cellDefinition = ExcelUtil.genarateCellsByRange(max, false, cellCount);

                int cellDefinitionIndex = 0;
                for (int i = 0; i < rowsCount; i++) {
                    List<CustomCell> cells = new ArrayList<>(4);
                    int limit = 2;
                    List<CellData> collect = values.stream().flatMap(Collection::stream).sorted(Comparator.comparing(CellData::getPosition)).skip((long) i * limit).limit(limit).collect(Collectors.toList());
                    //填充空白
                    if (collect.size() < limit) {
                        CellData cellData = new CellData("", 1, null);
                        collect.add(cellData);
                    }
                    for (CellData cd : collect) {
                        CustomCell cd1 = cellDefinition.get(cellDefinitionIndex++);
                        cells.add(new CustomCell(cd.getTitleName(), cd1.getStart(), cd1.getEnd()));
                        CustomCell cd2 = cellDefinition.get(cellDefinitionIndex++);
                        Field field = cd.getField();
                        String fieldValue = "";
                        if (field != null) {
                            field.setAccessible(true);
                            try {
                                Object o = field.get(comInfo);
                                if (Objects.nonNull(o)) {
                                    fieldValue = o.toString();
                                }
                            } catch (IllegalAccessException e) {
                                log.error("通过反射获取对象属性异常 field：{},obj:{}", field.getName(), JSON.toJSONString(comInfo), e);
                            }
                        }
                        cells.add(new CustomCell(fieldValue, cd2.getStart(), cd2.getEnd()));
                    }
                    cellDefinitionIndex = 0;
                    rows.add(new CustomRow(RowHeightConstant.ROW_HEIGHT_18, cells));
                }
                tableDefinition.setRowsData(rows);
            }
        } else {
            Field[] declaredFields = byType.getDeclaredFields();
            cellCount = declaredFields.length;
            //处理单行数据
            List<CustomCell> cells = ExcelUtil.genarateCellsByRange(max, false, cellCount);
            try {
                for (int i = 0; i < declaredFields.length; i++) {
                    declaredFields[i].setAccessible(true);
                    Object o = declaredFields[i].get(comInfo);
                    cells.get(i).setValue(o + "");
                }
                tableDefinition.setData(cells);
            } catch (IllegalAccessException e) {
                e.fillInStackTrace();
            }
        }
        return tableDefinition;
    }

}
